package file

import (
	"encoding/json"
	"net/http"
	"os"
	"strings"

	"chainmaker.org/chainmaker/smarteditor/conf"
	"chainmaker.org/chainmaker/smarteditor/container"
	"chainmaker.org/chainmaker/smarteditor/util"

	"chainmaker.org/chainmaker/smarteditor/event"
	"chainmaker.org/chainmaker/smarteditor/session"

	"github.com/88250/gulu"
)

// RemoveFileHandler handles request of removing file or directory.
func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
	if httpSession.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
	uid := httpSession.Values["uid"].(string)
	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		log.Error(err)
		result.Code = -1
		return
	}

	path := args["path"].(string)

	if gulu.Go.IsAPI(path) || util.BelongsGoPath(path) || !session.CanAccess(uid, path) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	err := container.SC.ResourceManager.RemoveFile(uid, path)
	if err != nil {
		log.Errorf("[RemoveFileHandler] remove file from resource manager fail. err:%v", err)
	}

	sid := args["sid"].(string)
	wSession := session.WideSessions.Get(sid)
	if wSession == nil {
		log.Errorf("remove  get sid %s found no wSession", sid)
		result.Code = -1
		result.Msg = sid + " get no wSession"
		return
	}
	if !removeFile(path) {
		result.Code = -1
		wSession.EventQueue.Queue <- &event.Event{Code: event.EvtCodeServerInternalError, Sid: sid,
			Data: "can't remove file " + path}
		return
	}
	user := conf.GetUser(uid)

	if util.IsContractRootDirectory(user.Workspace, path) {
		contractName := strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(path, conf.GetSrcDir(user.Workspace)), "/"), "/")
		deleteErr := conf.DeleteUserContractHidden(uid, contractName)
		if deleteErr != nil {
			log.Errorf("RemoveFileHandler uid %s ,path %s, failed %s",
				uid, path, deleteErr.Error())
		}
	}

	log.Debugf("Removed a file [%s] by user [%s]", path, wSession.UserID)
}

// removeFile removes file on the specified path.
func removeFile(path string) bool {
	if err := os.RemoveAll(path); nil != err {
		log.Errorf("Removes [%s] failed: [%s]", path, err.Error())
		return false
	}
	log.Debugf("Removed [%s]", path)
	return true
}
